home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_06_06 / v6n6055a.txt < prev    next >
Text File  |  1989-09-26  |  14KB  |  498 lines

  1. /* *********************************************************************
  2. *
  3.  *
  4.  *  A Simple Model for Hiding Surfaces
  5.  *  Jay Martin Anderson
  6.  *  Franklin & Marshall College, Lancaster, Pennsylvania
  7.  *  Tymlabs Corporation, Austin, Texas
  8.  *
  9.  *  This program draws a three-dimensional object described by a table
  10.  *  of faces using hidden-surface elimination.
  11.  *  The algorithm is described briefly in M. Berger, "Computer Graphics
  12.  *  with Pascal," (Benjamin/Cummings, 1986), and in somewhat greater
  13.  *  detail by R. J. Rost, reported in Creative Computing, February, 1984
  14. .
  15.  *
  16.  *  Implemented for HP CRTs on HP 3000, using Pascal and AGL (HP's graph
  17. ics
  18.  *     language, April, 1984; revised, April, 1986; March, 1988; revised
  19.  *     to use Tymlabs' C/3000 for the HP 3000, May, 1988.
  20.  *
  21.  *  Implemented May, 1988, for the Apple Macintosh (monochrome), using
  22.  *     Lightspeed C and Quickdraw graphics (Macintosh toolbox).
  23.  *
  24.  * ********************************************************************
  25. */
  26.  
  27.  /* ********************* #INCLUDEd files *****************************
  28. */
  29.  #include "stdio.h"
  30.   /* Use the "stdio" window provided by Lightspeed C, which is
  31.    * 500 pixels wide by 288 pixels tall, rather than using window
  32.    * management from Mac toolbox directly.
  33.    */
  34.  #include "unix.h"
  35.  #include "Quickdraw.h"
  36.  #include "math.h"
  37.  
  38.  /* ********************* Some Common DEFINEs *************************
  39. */
  40.  #define MAXFACES 60     /* maximum number of faces */
  41.  #define MAXPTS 100                    /* maximum number of vertices */
  42.  #define NVF 4       /* vertices/face; squares  */
  43.  #define HUGE_VAL 1.0E77    /* a very large number */
  44.  #define TRUE  1
  45.  #define FALSE 0
  46.  #define sysPatListID 0     /* Resource ID, patterns */
  47.  typedef float MATRIX[4][4];            /* 4x4 matrix of real numers */
  48.  struct faceS       /* what we know about a face */
  49.  {
  50.   float z;    /* smallest Z, eye coords, for face */
  51.   int color;    /* "color" of this face */
  52.   int v[NVF];    /* list of vertices for this face */
  53.  };
  54.  
  55.  /* ********************* Global Variables ****************************
  56. */
  57.  int v[MAXFACES][NVF];      /* vertex list */
  58.  float x0[MAXPTS], y0[MAXPTS], z0[MAXPTS]; /* original coordinates */
  59.  float xt[MAXPTS], yt[MAXPTS], zt[MAXPTS]; /* transformed coordinates */
  60.  float xs[MAXPTS], ys[MAXPTS];    /* screen coordinates */
  61.  struct faceS faceList[MAXFACES];   /* list of faces */
  62.  MATRIX view;        /* viewing transformation */
  63.  float eyex, eyey, eyez;     /* position of eye */
  64.  float fx, fy, fz;       /* where eye is focussing */
  65.  float ds;         /* scale factor */
  66.  float horizRotn;       /* rotation of horizon */
  67.  float n1, n2, n3;       /* normal to a face */
  68.  int numFaces, numVertices, numVisFaces;
  69.  
  70.  int readFaceData()
  71.  {
  72.   /* Hardcoded for one cube of size 2, centered at origin;
  73.    * Example 1.
  74.    */
  75.   /* for each vertex, its coordinates */
  76.   x0[0] =  1.0, y0[0] =  1.0, z0[0] =  1.0;
  77.   x0[1] = -1.0, y0[1] =  1.0, z0[1] =  1.0;
  78.   x0[2] = -1.0, y0[2] = -1.0, z0[2] =  1.0;
  79.   x0[3] =  1.0, y0[3] = -1.0, z0[3] =  1.0;
  80.   x0[4] =  1.0, y0[4] =  1.0, z0[4] = -1.0;
  81.   x0[5] = -1.0, y0[5] =  1.0, z0[5] = -1.0;
  82.   x0[6] = -1.0, y0[6] = -1.0, z0[6] = -1.0;
  83.   x0[7] =  1.0, y0[7] = -1.0, z0[7] = -1.0;
  84.   /* for each face, its vertex list in CCW order */
  85.   v[0][0] = 0, v[0][1] = 1, v[0][2] = 2, v[0][3] = 3; /* top */
  86.   v[1][0] = 1, v[1][1] = 5, v[1][2] = 6, v[1][3] = 2; /* rear */
  87.   v[2][0] = 3, v[2][1] = 2, v[2][2] = 6, v[2][3] = 7; /* left */
  88.   v[3][0] = 0, v[3][1] = 3, v[3][2] = 7, v[3][3] = 4; /* front */
  89.   v[4][0] = 1, v[4][1] = 0, v[4][2] = 4, v[4][3] = 5; /* right */
  90.   v[5][0] = 4, v[5][1] = 7, v[5][2] = 6, v[5][3] = 5; /* bottom */
  91.  
  92.   return(TRUE);
  93.  }
  94.  
  95.  #define COS1 0.540302
  96.  #define SIN1 0.841471
  97.  int getParams()
  98.  {
  99.   /* Hardcoded for a sequence of views of the one cube which is
  100.    * hardcoded in "readDataFile."  Values are initialized in "initStuff"
  101. .
  102.    */
  103.  
  104.    float tempx, tempy;
  105.  
  106.    /* Position of eye */
  107.    tempx = eyex;
  108.    tempy = eyey;
  109.  
  110.    /* Spiral the viewer, or eye, around the object; at each
  111.     * iteration, rotation by 1 radian, and move up by 1/2 unit.
  112.     * To save time, use defined constants for cos(1) and sin(1).
  113.     */
  114.    eyex = COS1*tempx - SIN1*tempy;
  115.    eyey = SIN1*tempx + COS1*tempy;
  116.    eyez += 0.5;
  117.  
  118.   /* Focus point; where eye is looking */
  119.    fx = fy = fz = 0.0;
  120.  
  121.    if (eyez > 10.0) return(FALSE);  /* that's enough */
  122.    else return(TRUE);
  123.  }
  124.  
  125.  void initMat(M)
  126.  MATRIX M;
  127.  {
  128.   /* Construct a 4x4 identity matrix */
  129.   int i, j;       /* subscript; loop index */
  130.  
  131.   for (i = 0; i < 4; i++)
  132.    for (j = 0; j < 4; j++)
  133.     M[i][j] = (i != j) ? 0.0 : 1.0;
  134.  }
  135.  
  136.  void multMat(M3, M1, M2)
  137.  MATRIX M1, M2, M3;
  138.  {
  139.   /* Multiply M1 x M2 and put result in M3; 4x4 square matrices */
  140.   int i, j, k;      /* subscript; loop index */
  141.  
  142.   for (i = 0; i < 4; i++)
  143.    for (j = 0; j < 4; j++)
  144.    {
  145.     M3[i][j] = 0.0;
  146.     for (k = 0; k < 4; k++) M3[i][j] += M1[i][k]*M2[k][j];
  147.    }
  148.  }
  149.  
  150.  void calcViewMatrix()
  151.  {
  152.   /* Calculate the viewing transformation matrix */
  153.   int i, j;     /* matrix subscripts; loop index */
  154.   MATRIX t1, t2;    /* temp matrices for transformation */
  155.   double d1, d2;    /* temporary results */
  156.  
  157.   initMat(view);
  158.  
  159.   /* translate origin to eye position */
  160.   view[3][0] = -eyex;
  161.   view[3][1] = -eyey;
  162.   view[3][2] = -eyez;
  163.   initMat(t1);
  164.  
  165.   /* rotate about x-axis by 90 degrees */
  166.   t1[1][1] = 0.0;
  167.   t1[2][2] = 0.0;
  168.   t1[1][2] = -1.0;
  169.   t1[2][1] = 1.0;
  170.   multMat(t2, view, t1);
  171.   for (i = 0; i < 4; i++)
  172.    for (j = 0; j < 4; j++) view[i][j] = t2[i][j];
  173.  initMat(t1);
  174.  
  175.   /* rotate about y-axis by an angle dependent on focus point */
  176.   fx = eyex - fx;
  177.   fy = eyey - fy;
  178.   fz = eyez - fz;
  179.   d1 = sqrt((double)(fx*fx + fy*fy));
  180.   if (fabs(d1) > 0.0001)
  181.   {
  182.    t1[0][0] = -fy/d1;
  183.    t1[2][2] = -fy/d1;
  184.    t1[0][2] =  fx/d1;
  185.    t1[2][0] = -fx/d1;
  186.    multMat(t2, view, t1);
  187.    for (i = 0; i < 4; i++)
  188.     for (j = 0; j < 4; j++) view[i][j] = t2[i][j];
  189.   }
  190.   initMat(t1);
  191.  
  192.   /* rotate about x-axis by angle dependent on focus point */
  193.   d2 = sqrt((double)(fx*fx + fy*fy  + fz*fz));
  194.   if (fabs(d2) > 0.0001)
  195.   {
  196.    t1[1][1] = d1/d2;
  197.    t1[2][2] = d1/d2;
  198.    t1[1][2] = fz/d2;
  199.    t1[2][1] = -fz/d2;
  200.    multMat(t2, view, t1);
  201.    for (i = 0; i < 4; i++)
  202.     for (j = 0; j < 4; j++) view[i][j] = t2[i][j];
  203.   }
  204.   initMat(t1);
  205.  
  206.   /* rotate about z-axis to rotate horizon */
  207.   horizRotn *= PI/180.0; /* convert degrees to radians */
  208.   t1[0][0] = t1[1][1] = (float)cos((double)horizRotn);
  209.   t1[0][1] = (float)sin((double)horizRotn);
  210.   t1[1][0] = -t1[0][1];
  211.   multMat(t2, view, t1);
  212.   for (i = 0; i < 4; i++)
  213.    for (j = 0; j < 4; j++) view[i][j] = t2[i][j];
  214.   initMat(t1);
  215.  
  216.   /* invert the z-axis */
  217.   t1[2][2] = -1.0;
  218.   /* and scale according to D/S ratio */
  219.   t1[0][0] = ds;
  220.   t1[1][1] = ds;
  221.   multMat(t2, view, t1);
  222.   for (i = 0; i < 4; i++)
  223.    for (j = 0; j < 4; j++) view[i][j] = t2[i][j];
  224. }
  225.  
  226. void initStuff()
  227. {
  228.  /* Whatever needs to be initialized; may be device-dependent;
  229.   * may be implementation-dependent.  Includes fixed parameters for
  230.   * this example.
  231.   */
  232.  
  233.   numFaces = 6;
  234.   numVertices = 8;
  235.  
  236.  /* Write at upper left of console window */
  237.  gotoxy(0,0);
  238.  puts("Example 1.  Cube.");
  239.  
  240.  /* Initial position of eye */
  241.  eyez = -10.0;
  242.  eyex = 7.50;
  243.  eyey = 13.0;
  244.  
  245.    /* Horizon rotation */
  246.    horizRotn = 0.0;
  247.    /* Scaling factor */
  248.    ds = 1.5;
  249. }
  250.  
  251. void finishStuff()
  252. {
  253.  /* Whatever needs to be closed, etc.  May be device-dependent;
  254.   * may be implementation-dependent.
  255.   *
  256.   * Nothing to do in this example.
  257.   */
  258. }
  259.  
  260. void transform(px, py, pz)
  261. float *px, *py, *pz;
  262. {
  263.  /* Transforms a point, pointed to by px, py, pz, by view transform */
  264.  
  265.  float temp1, temp2, temp3;
  266.  temp1 = *px, temp2 = *py, temp3 = *pz;
  267.  *px = view[0][0]*temp1+view[1][0]*temp2+view[2][0]*temp3+view[3][0];
  268.  *py = view[0][1]*temp1+view[1][1]*temp2+view[2][1]*temp3+view[3][1];
  269.  *pz = view[0][2]*temp1+view[1][2]*temp2+view[2][2]*temp3+view[3][2];
  270. }
  271.  
  272. void transformAll()
  273. {
  274.  /* Tr